module display_bus_02(

    input  wire        sclk             ,
    input  wire        resetb           ,
    input  wire        clk_mcu          ,
    input  wire        sclkin              ,
    input  wire        time_1s,
    input  wire        time_15ms,
    input  wire        time_250ms,

    //mcu ahb
    output      wire    [1:0]  HRESP_EXT           ,
    output      wire           HREADY_OUT_EXT      ,
    output      wire    [31:0] HRDATA_EXT          ,
    input       wire    [1:0]  HTRANS_EXT          ,
    input       wire    [31:0] HADDR_EXT           ,
    input       wire           HWRITE_EXT          ,
    input       wire           HSEL_EXT            ,
    input       wire    [31:0] HWDATA_EXT          ,
    input       wire    [2:0]  HSIZE_EXT           ,
    input       wire           HREADY_IN_EXT       ,

    //mcu GPIO
    output      wire   [7:0]GPIO0_I             ,
    input       wire   [7:0]GPIO0_O             ,
    input       wire   [7:0]nGPEN0              ,

    output      wire   [7:0]GPIO1_I             ,
    input       wire   [7:0]GPIO1_O             ,
    input       wire   [7:0]nGPEN1              ,

    output      wire   [7:0]GPIO2_I             ,
    input       wire   [7:0]GPIO2_O             ,
    input       wire   [7:0]nGPEN2              ,


    //和通讯模块接口
    output reg         send_end          ,
    output wire        send_buf_we       ,
    output wire [9:0]  send_buf_waddr    ,
    output wire [7:0]  send_buf_wdata    ,
    input  wire [7:0]  send_buf_rdata    ,

    output reg         mcu_rec_end                ,
    output reg  [1:0]  fpga_flag_next             ,
    input  wire        interrupt                  ,

    /****************phy *******************/
    output      wire                PHY_RST_N        ,
    output      wire                PHY_MDC            ,
    inout       tri                 PHY_MDIO        ,


     //给显示逻辑的参数设置
    output reg          set_d_ok,
    output wire  [15:0] set_addr,
    output wire  [7:0]  set_data,

 //   output wire         ext_d_ok,
 //   output wire  [15:0] ext_addr,

     //扩展接口
    input  wire [7:0]  sys_state_data,

    //
    output reg         id_is_valid,
    output reg  [63:0] id,

    //
    output reg         lock_enable,
    output reg  [31:0] lock,

    //逐点调整数据
    input  wire        I_sdram_ready,
    output reg         O_adjust_start,
//    output reg         O_sdram_refresh_en,
    output reg         adjust_data_valid,
    output wire [ 7:0] adjust_data,

    //和主控模块接口
    output reg         init_mode       ,
//    output reg         init_end        ,
    output reg         reboot_en       ,
    output reg         comm_en         ,
//    output reg         reconfig_en     ,
    output reg  [1:0]  reboot_sel      ,
//    output reg         reconfig_adjust_en  ,
    output reg         reconfig_pll_en     ,

    input  wire          frame_start ,
    input  wire          key_in   ,
    output reg           key_out  ,
    output reg     [3:0] change_mode,
    output wire    [9:0] ram_waddr_rgb ,
    output wire    [31:0]ram_wdata_rgb ,
    output reg           ram_wr_rgb   ,
    input  wire          kp_busy  ,
    
    
    output wire   [31:0] sdram_ram_data_w,
    input  wire   [31:0] sdram_ram_data_r,
    output wire   [ 9:0] sdram_ram_addr,
    output reg           sdram_ram_addr_wren,
    
    output reg    [23:0] sdram_addr_start,
    output reg           sdram_wr_or_rd,
    output reg           sdram_req,
    input  wire          sdram_busy,
    
    
    output wire [31:0] tout
);
//**********************************************/
//        信号定义
/************************************************/
reg         reconfig_pll_en_dly;
reg         reboot_flag;
reg  [1:0]  reboot_cnt;
reg         reboot_en_tmp;



my_count u_my_count(

    .clk_25m(sclkin),
    .rst_n(1'b1),
    .req(GPIO2_O[0]),
    .q({GPIO1_I,GPIO0_I})
);

wire  [1:0]  ext_d_ok ;
reg   [15:0] ext_addr ;

assign HRESP_EXT = 2'b0;

assign PHY_MDC = GPIO2_O[1];
assign PHY_MDIO = nGPEN2[2] ? 1'bZ : GPIO2_O[2];
assign GPIO2_I[2] = PHY_MDIO;
assign PHY_RST_N  = GPIO2_O[3];

assign GPIO2_I[4] = interrupt ;
// assign GPIO2_I[6] = key_in ;
reg [1:0]key_cnt;
always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        key_cnt <= 'b0;
    else if( key_in )
        key_cnt <= 'b0;
    else if( key_cnt[1]==0 && time_15ms )
        key_cnt <= key_cnt + 1;
    else 
        key_cnt <= key_cnt ;
end

assign GPIO2_I[6] = key_cnt[1] ;

assign GPIO2_I[7] = I_sdram_ready ;

wire [3:0]sel;
wire [31:0]addr;
wire [1:0]addr_l;
wire      wr_en_t;
reg  [15:0]wr_en;
wire [31:0]wdata;
wire [31:0]rdata0;
wire [31:0]rdata1;
wire [31:0]rdata2;
wire [31:0]rdata3;
// assign rdata2 = sys_state_data;
// assign rdata3 = send_buf_rdata;
ahb2ram_4 ahb2ram_3_inst(
                .hclk (clk_mcu)                  ,
                .hresetn (resetb )               ,
                .hwdata  (HWDATA_EXT)            ,
                .haddr   (HADDR_EXT)             ,
                .hwrite  (HWRITE_EXT)            ,// 1 - Write, 0 - Read
                .hsize   (HSIZE_EXT)             ,
                .hsel    (HSEL_EXT)              ,
                .htrans  (HTRANS_EXT)            ,
                .hrdata  (HRDATA_EXT)            ,
                .hready_out (HREADY_OUT_EXT)     ,

                .sclk   ( sclk   )               ,
                .sel    ( sel    )               ,
                .addr   ( addr   )               ,
                // .addr_l ( addr_l )               ,
                .wr_en  ( wr_en_t  )               ,
                .wdata  ( wdata  )               ,
                .rdata0 ( {sys_state_data,sys_state_data,sys_state_data,sys_state_data}  )              ,
                // .rdata0 ( {24'b0,sys_state_data}  )              ,
                // .rdata1 ( {send_buf_rdata,send_buf_rdata,send_buf_rdata,send_buf_rdata}  )              ,
                // .rdata2 ( {sys_state_data,sys_state_data,sys_state_data,sys_state_data}  )              ,
                // .rdata3 ( {send_buf_rdata,send_buf_rdata,send_buf_rdata,send_buf_rdata}  )              ,
                
                .rdata1 ( rdata1  )              ,
                .rdata2 ( 32'b0  )              ,
                .rdata3 ( rdata3  )              ,
                .tout ()
                );
always@ (posedge sclk) begin
    if(wr_en_t)begin
        wr_en <= 16'hffff;
    end
    else begin
        wr_en <= 16'h0000;
    end
end


reg [15:0]sel_ok;
always@ (posedge sclk) begin
    case(addr[27:24])
    4'd0:  begin
         sel_ok <= 16'b0000_0000_0000_0001 ;
    end
    4'd1:  begin
         sel_ok <= 16'b0000_0000_0000_0010 ;
    end
    4'd2:  begin
         sel_ok <= 16'b0000_0000_0000_0100 ;
    end
    4'd3:  begin
         sel_ok <= 16'b0000_0000_0000_1000 ;
    end

    4'd4:  begin
         sel_ok <= 16'b0000_0000_0001_0000 ;
    end
    4'd5:  begin
         sel_ok <= 16'b0000_0000_0010_0000 ;
    end
    4'd6:  begin
         sel_ok <= 16'b0000_0000_0100_0000 ;
    end
    4'd7:  begin
         sel_ok <= 16'b0000_0000_1000_0000 ;
    end

    4'd8:  begin
         sel_ok <= 16'b0000_0001_0000_0000 ;
    end
    4'd9:  begin
         sel_ok <= 16'b0000_0010_0000_0000 ;
    end
    4'd10:  begin
         sel_ok <= 16'b0000_0100_0000_0000 ;
    end
    4'd11:  begin
         sel_ok <= 16'b0000_1000_0000_0000 ;
    end

    4'd12:  begin
         sel_ok <= 16'b0001_0000_0000_0000 ;
    end
    4'd13:  begin
         sel_ok <= 16'b0010_0000_0000_0000 ;
    end
    4'd14:  begin
         sel_ok <= 16'b0100_0000_0000_0000 ;
    end
    4'd15:  begin
         sel_ok <= 16'b1000_0000_0000_0000 ;
    end
    endcase
end


/******************************************************/
//给显示逻辑的参数设置 在ahb   0xa100_0000 -0xa1ff_ffff
/******************************************************/
// assign set_d_ok = wr_en[1] && sel[0]  && sel_ok[1] ;
always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        set_d_ok <= 1'b0;
    else if (wr_en[1] && sel[0]  && sel_ok[1])
        set_d_ok <= 1'b1;
    else 
        set_d_ok <= 1'b0;
end
assign set_addr = addr[15:0]    ;
assign set_data =  wdata[7:0]  ;
// assign rdata0 =  sys_state_data;


/******************************************************/
// ext_addr的参数设置   0x0100_0000~0x0100_FFFF   ahb:0xa200_0000 -0xa200_ffff
/******************************************************/
assign ext_d_ok[0] = wr_en[2] && sel[0] &&  sel_ok[2]  ;

// always @(posedge sclk or negedge resetb) begin
    // if (!resetb)
        // ext_d_ok[0] <= 0;
    // else 
        // ext_d_ok[0] = wr_en_t && sel[0] &&  sel_ok[2]  ;
// end

//************************************************/
//        reboot保护
//************************************************/
always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        reboot_flag <= 1'b0;
    else if (ext_d_ok[0] == 1 && set_addr[7:2] == 6'h01)
        reboot_flag <= 1'b1;
    else if (reboot_cnt == 2'd0)
        reboot_flag <= 1'b0;
end

always @(posedge sclk or negedge resetb) begin
    if (!resetb)
        reboot_cnt <= 2'b0;
    else if (ext_d_ok[0] == 1 && set_addr[7:2] == 6'h01)
        reboot_cnt <= 2'd3;
    else if (time_1s && reboot_cnt != 2'b0)
        reboot_cnt <= reboot_cnt - 1'b1;
end

//************************************************/
//      reboot_sel
//************************************************/
always @(posedge sclk or negedge resetb)
    if (resetb == 0)
        reboot_sel <= 1'b0;
    else if (ext_d_ok[0] == 1 && set_addr[7:2] == 6'h01)
        reboot_sel <= wdata[9:8];

//************************************************/
//        reconfig_pll_en
//************************************************/
always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reconfig_pll_en <=0;
    else if (reconfig_pll_en_dly)
        reconfig_pll_en<=0;
    else if (ext_d_ok[0] == 1 && set_addr[7:2] == 6'h01)
        reconfig_pll_en<=wdata[24];

always@(posedge sclk)
    reconfig_pll_en_dly <= reconfig_pll_en;

/******************************************************/
// ext_addr的参数设置   0x1000_0000~0x1000_FFFF   ahb:0xa300_0000 -0xa000_ffff
/******************************************************/
assign ext_d_ok[1] = wr_en[3] && sel[0] && sel_ok[3]  ;

// always @(posedge sclk or negedge resetb) begin
    // if (!resetb)
        // ext_d_ok[1] <= 0;
    // else 
        // ext_d_ok[1] = wr_en && sel[0] &&  sel_ok[3]  ;
// end

always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reboot_en_tmp<=0;
    else if (ext_d_ok[1] == 1)
        reboot_en_tmp<=1;

always@(posedge sclk or negedge resetb)
    if (resetb == 0)
        reboot_en<=1'b0;
    else
        reboot_en<=reboot_en_tmp&&reboot_flag;



/******************************************************/
//id                 在ahb   0xa400_0000 -0xa400_0007
/******************************************************/
always @(posedge sclk)begin
    if (wr_en[4] && sel[0] && sel_ok[4])
    case (set_addr[2])
        0: begin
            id[63:56] <= wdata[7:0]; // year
            id[55:48] <= wdata[15:8];  // month
            id[47:40] <= wdata[23:16];  // day
            id[39:32] <= wdata[31:24];
            end
        1:begin
            id[31:24] <= wdata[7:0];
            id[23:16] <= wdata[15:0];
            id[15:8]  <= wdata[23:16];
            id[7:0]   <= wdata[31:24];
          end
    endcase
end

always@(posedge sclk  or negedge resetb)begin
    if (resetb == 0)
        id_is_valid <= 1'b0;
    else if (wr_en[4] && sel[0] &&  sel_ok[4] && set_addr[2] == 1'd1)
        id_is_valid <= 1'b1;
    else
        id_is_valid <= 1'b0;
end


/******************************************************/
//lock                 在ahb   0xa500_0000 -0xa500_0004
/******************************************************/
always @(posedge sclk)begin
    if (wr_en[5] && sel[0] &&  sel_ok[5])
    case (set_addr[2])
        0: begin
            lock_enable <= (wdata[7:0] == 'h3A);
            lock[31:24] <= wdata[15:8];
            lock[23:16] <= wdata[23:16];
            lock[15:8]  <= wdata[31:24];
        end
        1: begin
            lock[7:0]   <= wdata[7:0];
        end
    endcase
end

/******************************************************/
//com_ctrl控制   在ahb   0xa600_0000
/******************************************************/
always@(posedge sclk  or negedge resetb)begin
    if (resetb == 0)
        fpga_flag_next <= 0;
    else if (wr_en[6] && sel[0] && sel_ok[6] && set_addr[3:0] == 4'b0 )
        fpga_flag_next <= wdata[1:0];
end

always@(posedge sclk  or negedge resetb)begin
    if (resetb == 0)
        mcu_rec_end <= 0;
    else if (wr_en[6] && sel[0] &&  sel_ok[6] && set_addr[3:0] == 4'd0 )
        mcu_rec_end    <= 1 ;
    else
        mcu_rec_end    <=  0;
end


/******************************************************/
//系统状态 在ahb   0xa700_0000
/******************************************************/
always@(posedge sclk  or negedge resetb)begin
    if (resetb == 0)
        init_mode <= 0;
    else if (wr_en[7] && sel[0] &&  sel_ok[7] && set_addr[3:0] == 4'b0 )
        init_mode <= wdata[0];
end

always@(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        comm_en <= 0;
    else if (wr_en[7] && sel[0] && sel_ok[7] && set_addr[3:0] == 4'd4 )
        comm_en <= wdata[0];
end

always@(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        O_adjust_start <= 0;
    else if (wr_en[7] && sel[0] &&  sel_ok[7] && set_addr[3:0] == 4'd8 )
        O_adjust_start <= wdata[0];
end


/******************************************************/
//逐点调整数据 在ahb   0xa800_0000
/******************************************************/
always@(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        adjust_data_valid <= 0;
    else if (wr_en[8] && sel[0] &&  sel_ok[8] )
        adjust_data_valid <= 1;
    else
        adjust_data_valid <= 0;
end

assign adjust_data = wdata[7:0];

/******************************************************/
//key状态 在ahb   0xa900_0000
//key数据 在ahb   0xb000_0000
/******************************************************/

// assign ram_wr_rgb = wr_en[0] && sel[1]  && sel_ok[0] ;
always@(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        ram_wr_rgb <= 0;
    else 
        ram_wr_rgb <=  wr_en[0] && sel[1]  && sel_ok[0] ;
end


assign ram_waddr_rgb = addr[9:0]    ;
assign ram_wdata_rgb =  wdata[31:0]  ;


always@(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        key_out <= 0;
    else if (wr_en[9] && sel[0] &&  sel_ok[9] && set_addr[3:0] == 4'd0)
        key_out <= wdata[0] ;
    else 
        key_out <= 0;
end

//帧开始 中断， 60hz 16.67ms
reg [3:0] frame_start_reg;
always@(posedge sclk or negedge resetb)begin
    if ( resetb == 0 )
        frame_start_reg[3:0] <= 4'b0;
    else if( frame_start )
        // frame_start_reg[3:0] <= 4'b1111;
        frame_start_reg[3:0] <= frame_start_reg[3:0] + 1'b1 ;
    // else 
        // frame_start_reg[3:0] <= {1'b0 , frame_start_reg[3:1] } ;
end
assign GPIO2_I[5] = frame_start_reg[2] ;


//sdram 
//缓存在 0xb1000000
//操作   0xaa00_0000
//状态   0xd000_0000

assign      sdram_ram_data_w = wdata[31:0] ;
assign      rdata1   = sdram_ram_data_r;
assign      sdram_ram_addr = addr[9:0]    ;

// always@(posedge sclk or negedge resetb)begin
    // sdram_ram_data_w <= wdata[31:0] ;
    // sdram_ram_addr <= addr[9:0]    ;
// end

// assign      sdram_ram_addr_wren = wr_en[1] && sel[1]  && sel_ok[1] ;
always@(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        sdram_ram_addr_wren <= 0;
    else if ( wr_en[1] && sel[1]  && sel_ok[1] )
        sdram_ram_addr_wren <= 1 ;
    else 
        sdram_ram_addr_wren <= 0;
end

always@(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        sdram_req <= 0;
    else if (wr_en[10] && sel[0] &&  sel_ok[10] && set_addr[3:0] == 4'd0)
        sdram_req <= wdata[0] ;
    else 
        sdram_req <= 0;
end

always@(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        sdram_wr_or_rd <= 0;
    else if (wr_en[10] && sel[0] &&  sel_ok[10] && set_addr[3:0] == 4'd4)
        sdram_wr_or_rd <= wdata[0] ;
end

always@(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        sdram_addr_start <= 0;
    else if (wr_en[10] && sel[0] &&  sel_ok[10] && set_addr[3:0] == 4'd8)
        sdram_addr_start <= wdata[23:0] ;
end

reg  [31:0]state_reg;
assign rdata3 = state_reg;
always @(posedge sclk or negedge resetb)begin
    if (resetb == 0)
        state_reg <= 0 ;
    else if ( sel[3] &&  sel_ok[0] )
        case(set_addr[7:0])
            8'h00: begin
                        state_reg[0] <= sdram_busy ;
                        state_reg[7:1] <= 1'b0 ;
                        state_reg[8] <= kp_busy ;
                        state_reg[15:9] <= 1'b0 ;
                        state_reg[31:16] <= 16'b0 ;
                   end
            default state_reg<='d0;
        endcase
end
/************************************************/
//        测试信号
/************************************************/
assign  tout = 0;

endmodule

